home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / print_jvm_class.e < prev    next >
Text File  |  2000-03-25  |  61KB  |  1,699 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class PRINT_JVM_CLASS
  17.    --
  18.    -- The `print_jvm_class' command.
  19.    --
  20.  
  21. inherit COMMAND_FLAGS; CP_INFO_TAGS;
  22.  
  23. creation make
  24.  
  25. feature {NONE}
  26.  
  27.    command_name: STRING is "print_jvm_class";
  28.  
  29.    bytes: FIXED_ARRAY[INTEGER] is
  30.          -- All bytes of the class file.
  31.       once
  32.          !!Result.with_capacity(4096);
  33.       end;
  34.  
  35.    constant_pool_count: INTEGER;
  36.  
  37.    this_class_idx: INTEGER;
  38.  
  39.    super_class_idx: INTEGER;
  40.  
  41.    interfaces_count: INTEGER;
  42.  
  43.    fields_count: INTEGER;
  44.  
  45.    methods_count: INTEGER;
  46.  
  47.    attributes_count: INTEGER;
  48.  
  49.    make is
  50.       local
  51.          path: STRING;
  52.          file_of_bytes: BINARY_FILE_READ;
  53.          byte, i, index: INTEGER;
  54.          s: STRING;
  55.          interface_idx: INTEGER;
  56.          access_flags: BIT Integer_bits;
  57.       do
  58.          if argument_count /= 1 then
  59.             system_tools.bad_use_exit("print_jvm_class");
  60.          elseif is_flag_version(argument(1)) then
  61.          else
  62.             path := argument(1).twin;
  63.             if not path.has_suffix(".class") then
  64.                path.append(".class");
  65.             end;
  66.             !!file_of_bytes.connect_to(path);
  67.             if file_of_bytes.is_connected then
  68.                from
  69.                   io.put_string("Contents of file %"");
  70.                   io.put_string(file_of_bytes.path);
  71.                   io.put_string("%".%N");
  72.                   file_of_bytes.read_byte;
  73.                   if file_of_bytes.end_of_input then
  74.                      bad_class_file("Invalid empty class file.",0);
  75.                   end;
  76.                until
  77.                   file_of_bytes.end_of_input
  78.                loop
  79.                   byte := file_of_bytes.last_byte;
  80.                   bytes.add_last(byte)
  81.                   file_of_bytes.read_byte;
  82.                end;
  83.                file_of_bytes.disconnect;
  84.                io.put_string("Total bytes: ");
  85.                io.put_integer(bytes.count);
  86.                io.put_new_line;
  87.                io.put_string("Magic number: ");
  88.                s := hexa4_at(0);
  89.                if not ("0xCAFEBABE").is_equal(s) then
  90.                   bad_class_file("Invalid Magic number.",0);
  91.                else
  92.                   io.put_string(s);
  93.                   io.put_new_line;
  94.                end;
  95.                io.put_string("Minor version: ");
  96.                io.put_string(hexa2_at(4));
  97.                io.put_new_line;
  98.                io.put_string("Major version: ");
  99.                io.put_string(hexa2_at(6));
  100.                io.put_new_line;
  101.                io.put_string("Constant pool count: ");
  102.                constant_pool_count := u2_integer_at(8);
  103.                io.put_integer(constant_pool_count);
  104.                io.put_new_line;
  105.                io.put_string("Loading constant pool items :%N");
  106.                from
  107.                   constant_pool.reset(constant_pool_count - 1);
  108.                   index := 10; -- of first item in constant pool.
  109.                   i := 1;
  110.                until
  111.                   i >= constant_pool_count
  112.                loop
  113.                   index := load_cp_info(i,index);
  114.                   i := i + 1;
  115.                end;
  116.                io.put_string("Constant pool view :%N");
  117.                from
  118.                   index := 10; -- of first item in constant pool.
  119.                   i := 1;
  120.                until
  121.                   i >= constant_pool_count
  122.                loop
  123.                   tmp_string.clear;
  124.                   integer_to_hexa_in(i,tmp_string);
  125.                   tmp_string.extend(' ');
  126.                   extend_string(tmp_string,' ',6);
  127.                   i.append_in(tmp_string);
  128.                   tmp_string.extend(' ');
  129.                   extend_string(tmp_string,' ',12);
  130.                   tmp_string.extend('(');
  131.                   integer_to_hexa_in(index,tmp_string);
  132.                   tmp_string.extend(')');
  133.                   extend_string(tmp_string,' ',20);
  134.                   tmp_string.append(" : ");
  135.                   io.put_string(tmp_string);
  136.                   index := print_cp_info(i,index);
  137.                   io.put_new_line;
  138.                   i := i + 1;
  139.                end;
  140.                io.put_string("Access flag: ");
  141.                io.put_string(hexa2_at(index));
  142.                io.put_character(' ');
  143.                access_flags := bytes.item(index + 1).to_bit;
  144.                if (access_flags and 1B).to_boolean then
  145.                   io.put_string("public ");
  146.                end;
  147.                if (access_flags and 10000B).to_boolean then
  148.                   io.put_string("final (no subclass)");
  149.                end;
  150.                if (access_flags and 100000B).to_boolean then
  151.                   io.put_string("invokespecial (for superclass) ");
  152.                end;
  153.                access_flags := bytes.item(index).to_bit;
  154.                if (access_flags and 10B).to_boolean then
  155.                   io.put_string("interface ");
  156.                end;
  157.                if (access_flags and 100B).to_boolean then
  158.                   io.put_string("abstract ");
  159.                end;
  160.                io.put_new_line;
  161.                index := index + 2;
  162.                io.put_new_line;
  163.                io.put_string("This Class: ");
  164.                this_class_idx := u2_integer_at(index);
  165.                index := index + 2;
  166.                if constant_pool.is_class(this_class_idx) then
  167.                   tmp_string.copy(" is ");
  168.                   constant_pool.view_in(tmp_string,this_class_idx);
  169.                   io.put_string(tmp_string);
  170.                else
  171.                   io.put_string("??%N");
  172.                   bad_class_file("Bad `this_class' value.",index - 2);
  173.                end;
  174.                io.put_new_line;
  175.                io.put_string("Super Class: ");
  176.                super_class_idx := u2_integer_at(index);
  177.                index := index + 2;
  178.                if constant_pool.is_class(super_class_idx) then
  179.                   tmp_string.copy("is ");
  180.                   constant_pool.view_in(tmp_string,super_class_idx);
  181.                   io.put_string(tmp_string);
  182.                else
  183.                   io.put_string("??%N");
  184.                   bad_class_file("Bad `super_class' value.",index - 2);
  185.                end;
  186.                io.put_new_line;
  187.                io.put_string("Interfaces count: ");
  188.                interfaces_count := u2_integer_at(index);
  189.                index := index + 2;
  190.                io.put_integer(interfaces_count);
  191.                i := interfaces_count;
  192.                if i > 0 then
  193.                   io.put_string(" {");
  194.                   from
  195.                   until
  196.                      i = 0
  197.                   loop
  198.                      interface_idx := u2_integer_at(index);
  199.                      index := index + 2;
  200.                      io.put_integer(interface_idx);
  201.                      i := i - 1;
  202.                      if i > 0 then
  203.                         io.put_character(',');
  204.                      end;
  205.                   end;
  206.                   io.put_character('}');
  207.                end;
  208.                io.put_new_line;
  209.                io.put_string("----- Fields count: ");
  210.                fields_count := u2_integer_at(index);
  211.                index := index + 2;
  212.                io.put_integer(fields_count);
  213.                io.put_new_line;
  214.                from
  215.                   i := 1
  216.                until
  217.                   i > fields_count
  218.                loop
  219.                   io.put_integer(i);
  220.                   if i < 10 then
  221.                      io.put_string("   ");
  222.                   elseif i < 100 then
  223.                      io.put_string("  ");
  224.                   else
  225.                      io.put_string(" ");
  226.                   end;
  227.                   io.put_string(": ");
  228.                   index := print_field_info(index);
  229.                   io.put_new_line;
  230.                   i := i + 1;
  231.                end;
  232.                io.put_string("----- Methods count: ");
  233.                methods_count := u2_integer_at(index);
  234.                index := index + 2;
  235.                io.put_integer(methods_count);
  236.                io.put_new_line;
  237.                from
  238.                   i := 1
  239.                until
  240.                   i > methods_count
  241.                loop
  242.                   io.put_integer(i);
  243.                   if i < 10 then
  244.                      io.put_string("   ");
  245.                   elseif i < 100 then
  246.                      io.put_string("  ");
  247.                   else
  248.                      io.put_string(" ");
  249.                   end;
  250.                   io.put_string(": ");
  251.                   index := print_method_info(index);
  252.                   io.put_new_line;
  253.                   i := i + 1;
  254.                end;
  255.                io.put_string("Attributes count: ");
  256.                attributes_count := u2_integer_at(index);
  257.                index := index + 2;
  258.                io.put_integer(attributes_count);
  259.                io.put_new_line;
  260.                from
  261.                   i := 1
  262.                until
  263.                   i > attributes_count
  264.                loop
  265.                   io.put_integer(i);
  266.                   if i < 10 then
  267.                      io.put_string("   ");
  268.                   elseif i < 100 then
  269.                      io.put_string("  ");
  270.                   else
  271.                      io.put_string(" ");
  272.                   end;
  273.                   io.put_string(": ");
  274.                   index := print_attribute_info(index);
  275.                   io.put_new_line;
  276.                   i := i + 1;
  277.                end;
  278.                check
  279.                   index = bytes.upper + 1
  280.                end;
  281.             else
  282.                io.put_string("File %"");
  283.                io.put_string(path);
  284.                io.put_string("%" not found.%N");
  285.             end;
  286.          end;
  287.       end;
  288.  
  289. feature {NONE} -- Low level access in `bytes' :
  290.  
  291.    character_at(index: INTEGER): CHARACTER is
  292.       do
  293.          Result := bytes.item(index).to_character;
  294.       end;
  295.  
  296.    u2_at(index: INTEGER): STRING is
  297.       do
  298.          !!Result.make(2);
  299.          Result.extend(character_at(index + 0));
  300.          Result.extend(character_at(index + 1));
  301.       end;
  302.  
  303.    u4_at(index: INTEGER): STRING is
  304.       do
  305.          !!Result.make(4);
  306.          Result.extend(character_at(index + 0));
  307.          Result.extend(character_at(index + 1));
  308.          Result.extend(character_at(index + 2));
  309.          Result.extend(character_at(index + 3));
  310.       end;
  311.  
  312.    u8_at(index: INTEGER): STRING is
  313.       do
  314.          !!Result.make(8);
  315.          Result.extend(character_at(index + 0));
  316.          Result.extend(character_at(index + 1));
  317.          Result.extend(character_at(index + 2));
  318.          Result.extend(character_at(index + 3));
  319.          Result.extend(character_at(index + 4));
  320.          Result.extend(character_at(index + 5));
  321.          Result.extend(character_at(index + 6));
  322.          Result.extend(character_at(index + 7));
  323.       end;
  324.  
  325.    hexa1_at(index: INTEGER): STRING is
  326.       do
  327.          !!Result.copy("0x");
  328.          bytes.item(index).to_character.to_hexadecimal_in(Result);
  329.       end;
  330.  
  331.    hexa2_at(index: INTEGER): STRING is
  332.       do
  333.          !!Result.copy("0x");
  334.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  335.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  336.       end;
  337.  
  338.    hexa4_at(index: INTEGER): STRING is
  339.       do
  340.          !!Result.copy("0x");
  341.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  342.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  343.          bytes.item(index + 2).to_character.to_hexadecimal_in(Result);
  344.          bytes.item(index + 3).to_character.to_hexadecimal_in(Result);
  345.       end;
  346.  
  347.    hexa8_at(index: INTEGER): STRING is
  348.       do
  349.          !!Result.copy("0x");
  350.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  351.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  352.          bytes.item(index + 2).to_character.to_hexadecimal_in(Result);
  353.          bytes.item(index + 3).to_character.to_hexadecimal_in(Result);
  354.          bytes.item(index + 4).to_character.to_hexadecimal_in(Result);
  355.          bytes.item(index + 5).to_character.to_hexadecimal_in(Result);
  356.          bytes.item(index + 6).to_character.to_hexadecimal_in(Result);
  357.          bytes.item(index + 7).to_character.to_hexadecimal_in(Result);
  358.       end;
  359.  
  360.    u2_integer_at(index: INTEGER): INTEGER is
  361.       do
  362.          Result := bytes.item(index) * 256 + bytes.item(index + 1);
  363.       end;
  364.  
  365.    u4_integer_at(index: INTEGER): INTEGER is
  366.       do
  367.          Result := bytes.item(index);
  368.          Result := Result * 256;
  369.          Result := Result + bytes.item(index + 1);
  370.          Result := Result * 256;
  371.          Result := Result + bytes.item(index + 2);
  372.          Result := Result * 256;
  373.          Result := Result + bytes.item(index + 3);
  374.       end;
  375.  
  376. feature {NONE} -- Basic stuff to view values :
  377.  
  378.    integer_to_hexa_in(int: INTEGER; str: STRING) is
  379.       require
  380.          int >= 0
  381.       do
  382.          str.append("0x");
  383.          inspect
  384.             int
  385.          when 0 .. 255 then
  386.             int.to_character.to_hexadecimal_in(str);
  387.          when 256 .. 65535 then
  388.             (int \\ 256).to_character.to_hexadecimal_in(str);
  389.             (int // 256).to_character.to_hexadecimal_in(str);
  390.          end;
  391.       end;
  392.  
  393.    extend_string(s: STRING; c: CHARACTER; length: INTEGER) is
  394.       do
  395.          from
  396.          until
  397.             s.count >= length
  398.          loop
  399.             s.extend(c);
  400.          end;
  401.       end;
  402.  
  403.  
  404. feature {NONE}
  405.  
  406.    bad_class_file(msg: STRING; at: INTEGER) is
  407.          -- If `at' is greater than 0, the corresponding byte
  408.          -- is shown during the class file dump.
  409.       require
  410.          bytes.valid_index(at)
  411.       local
  412.          fz_visible, fz_hexadec: STRING;
  413.          index: INTEGER;
  414.          byte: CHARACTER;
  415.          left_margin: INTEGER;
  416.       do
  417.          io.put_string(msg);
  418.          io.put_new_line;
  419.          io.put_string("Class file dump:%N");
  420.          from
  421.             !!fz_visible.make(16);
  422.             !!fz_hexadec.make(32);
  423.          until
  424.             index > bytes.upper
  425.          loop
  426.             if fz_visible.is_empty then
  427.                tmp_string.clear;
  428.                integer_to_hexa_in(index,tmp_string);
  429.                tmp_string.extend(' ');
  430.                extend_string(tmp_string,' ',9);
  431.                index.append_in(tmp_string);
  432.                tmp_string.extend(' ');
  433.                extend_string(tmp_string,' ',15);
  434.                io.put_string(tmp_string);
  435.                left_margin := tmp_string.count;
  436.             end;
  437.             byte := character_at(index);
  438.             byte.to_hexadecimal_in(fz_hexadec);
  439.             inspect
  440.                byte.code
  441.             when 32 .. 126 then
  442.                fz_visible.extend(byte);
  443.             else
  444.                fz_visible.extend('.');
  445.             end
  446.             if fz_visible.count = 16 then
  447.                show_dump_line(fz_hexadec,fz_visible,left_margin,index,at);
  448.             end;
  449.             index := index + 1;
  450.          end;
  451.          if fz_visible.count > 0 then
  452.             from
  453.                index := index - 1;
  454.             until
  455.                fz_visible.count = 16
  456.             loop
  457.                fz_visible.extend(' ');
  458.                fz_hexadec.append("  ");
  459.                index := index + 1;
  460.             end;
  461.             show_dump_line(fz_hexadec,fz_visible,left_margin,index,at);
  462.          end;
  463.          die_with_code(exit_failure_code);
  464.       end;
  465.  
  466.    show_dump_line(hexadec, visible: STRING; left_margin, index, at: INTEGER) is
  467.          -- Where `index - 15' is the index of `visible.item(1)'.
  468.       require
  469.          bytes.valid_index(at);
  470.          visible.count = 16;
  471.          hexadec.count = 32
  472.       local
  473.          min, max, i: INTEGER;
  474.       do
  475.          io.put_string(hexadec);
  476.          io.put_string(" ");
  477.          io.put_string(visible);
  478.          io.put_new_line;
  479.          min := index - 15;
  480.          max := index;
  481.          if (at > 0) and (min <= at) and (at <= max) then
  482.             from
  483.                tmp_string.clear;
  484.                extend_string(tmp_string,'_',left_margin);
  485.                i := min;
  486.             until
  487.                i = at
  488.             loop
  489.                tmp_string.append("__");
  490.                i := i + 1;
  491.             end;
  492.             io.put_string(tmp_string);
  493.             io.put_string("^^%N*** Error at this byte%N");
  494.             io.put_string("Remainder of the class file :%N");
  495.          end;
  496.          visible.clear;
  497.          hexadec.clear;
  498.       ensure
  499.          visible.is_empty;
  500.          hexadec.is_empty
  501.       end;
  502.  
  503. feature {NONE}
  504.  
  505.    load_cp_info(i: INTEGER; index: INTEGER): INTEGER is
  506.          -- Gives the index of the following item.
  507.       local
  508.          tag, i2, length: INTEGER;
  509.          utf8: STRING;
  510.       do
  511.          tmp_string.clear;
  512.          tmp_string.append("item #");
  513.          i.append_in(tmp_string);
  514.          extend_string(tmp_string,' ',8);
  515.          tmp_string.append(" : ");
  516.          io.put_string(tmp_string);
  517.          tag := bytes.item(index);
  518.          inspect
  519.             tag.to_character
  520.          when Constant_class then
  521.             io.put_string("CONSTANT_Class");
  522.             constant_pool.set_class(i,u2_at(index + 1));
  523.             Result := index + 3;
  524.          when Constant_fieldref then
  525.             io.put_string("CONSTANT_Fieldref");
  526.             constant_pool.set_fieldref(i,u4_at(index + 1));
  527.             Result := index + 5;
  528.          when Constant_methodref then
  529.             io.put_string("CONSTANT_Methodref");
  530.             constant_pool.set_methodref(i,u4_at(index + 1));
  531.             Result := index + 5;
  532.          when Constant_interfacemethodref then
  533.             io.put_string("CONSTANT_InterfaceMethodref");
  534.             constant_pool.set_interface_methodref(i,u4_at(index + 1));
  535.             Result := index + 5;
  536.          when Constant_string then
  537.             io.put_string("CONSTANT_String");
  538.             constant_pool.set_string(i,u2_at(index + 1));
  539.             Result := index + 3;
  540.          when Constant_integer then
  541.             io.put_string("CONSTANT_Integer");
  542.             constant_pool.set_integer(i,u4_at(index + 1));
  543.             Result := index + 5;
  544.          when Constant_float then
  545.             io.put_string("CONSTANT_Float");
  546.             constant_pool.set_float(i,u4_at(index + 1));
  547.             Result := index + 5;
  548.          when Constant_long then
  549.             io.put_string("CONSTANT_Long");
  550.             constant_pool.set_long(i,u8_at(index + 1));
  551.             Result := index + 9;
  552.          when Constant_double then
  553.             io.put_string("CONSTANT_Double");
  554.             constant_pool.set_double(i,u8_at(index + 1));
  555.             Result := index + 9;
  556.          when Constant_name_and_type then
  557.             io.put_string("CONSTANT_NameandType");
  558.             constant_pool.set_name_and_type(i,u4_at(index + 1));
  559.             Result := index + 5;
  560.          when Constant_utf8 then
  561.             io.put_string("CONSTANT_Utf8");
  562.             length := u2_integer_at(index + 1);
  563.             Result := index + 3;
  564.             !!utf8.make(length + 2);
  565.             utf8.extend(character_at(index + 1));
  566.             utf8.extend(character_at(index + 2));
  567.             from
  568.                i2 := length;
  569.             until
  570.                i2 = 0
  571.             loop
  572.                utf8.extend(character_at(Result));
  573.                Result := Result + 1;
  574.                i2 := i2 - 1;
  575.             end;
  576.             constant_pool.set_utf8(i,utf8);
  577.          else
  578.             io.put_string("Error while loading constant pool.%N");
  579.             io.put_string("Problem with item #");
  580.             io.put_integer(i);
  581.             io.put_string("%NBad cp_info tag : ");
  582.             io.put_integer(tag);
  583.             io.put_string("%N");
  584.             bad_class_file("Bad constant pool.",index);
  585.          end;
  586.          io.put_new_line;
  587.       end;
  588.  
  589. feature {NONE}
  590.  
  591.    u2_to_integer(u2: STRING): INTEGER is
  592.       require
  593.          u2.count = 2
  594.       do
  595.          Result := u2.item(1).code;
  596.          Result := Result * 256;
  597.          Result := Result + u2.item(2).code;
  598.       ensure
  599.          Result >= 0
  600.       end;
  601.  
  602.    print_cp_info(i: INTEGER; index: INTEGER): INTEGER is
  603.          -- Gives the index of the following item.
  604.       local
  605.          tag: INTEGER;
  606.          cp_info: CP_INFO;
  607.          info: STRING;
  608.          class_idx, name_idx, type_idx, string_idx: INTEGER;
  609.       do
  610.          tag := bytes.item(index);
  611.          cp_info := constant_pool.item(i);
  612.          info := cp_info.info;
  613.          check
  614.             tag.to_character = cp_info.tag
  615.          end;
  616.          inspect
  617.             tag.to_character
  618.          when Constant_class then -- CONSTANT_Class :
  619.             io.put_string("class at ");
  620.             class_idx := u2_to_integer(info);
  621.             if constant_pool.valid_index(class_idx) then
  622.                io.put_integer(class_idx);
  623.                io.put_string(": ");
  624.                cp_info := constant_pool.item(class_idx);
  625.                if cp_info.tag.code = 1 then
  626.                   tmp_string.clear;
  627.                   constant_pool.view_in(tmp_string,i);
  628.                   io.put_string(tmp_string);
  629.                else
  630.                   io.put_string("%NUtf8 index expected.%N");
  631.                   bad_class_file("Bad constant pool.",index + 1);
  632.                end;
  633.             else
  634.                io.put_string("Class index out of range.%N");
  635.                bad_class_file("Bad constant pool.",index + 1);
  636.             end;
  637.             Result := index + 3;
  638.          when Constant_fieldref then -- CONSTANT_Fieldref :
  639.             io.put_string("fieldref class: ");
  640.             print_cp_info_fields_methods(index,info);
  641.             Result := index + 5;
  642.          when Constant_methodref then -- CONSTANT_Methodref :
  643.             io.put_string("methodref class: ");
  644.             print_cp_info_fields_methods(index,info);
  645.             Result := index + 5;
  646.          when Constant_interfacemethodref then -- CONSTANT_InterfaceMethodref :
  647.             io.put_string("interface methodref class: ");
  648.             print_cp_info_fields_methods(index,info);
  649.             Result := index + 5;
  650.          when Constant_string then -- CONSTANT_String :
  651.             io.put_string("string at ");
  652.             string_idx := u2_to_integer(info);
  653.             if constant_pool.valid_index(string_idx) then
  654.                io.put_integer(string_idx);
  655.                io.put_string(" : %"");
  656.                cp_info := constant_pool.item(string_idx);
  657.                if cp_info.tag.code = 1 then
  658.                   tmp_string.clear;
  659.                   constant_pool.view_in(tmp_string,i);
  660.                   io.put_string(tmp_string);
  661.                   io.put_string("%"");
  662.                else
  663.                   io.put_string("%NUtf8 index expected.%N");
  664.                   bad_class_file("Bad constant pool.",index + 1);
  665.                end;
  666.             else
  667.                io.put_string("??%NString index out of range.%N");
  668.                bad_class_file("Bad constant pool.",index + 1);
  669.             end;
  670.             Result := index + 3;
  671.          when Constant_integer then -- CONSTANT_Integer :
  672.             io.put_string("integer: ");
  673.             io.put_string(hexa4_at(index + 1));
  674.             Result := index + 5;
  675.          when Constant_float then -- CONSTANT_Float :
  676.             io.put_string("float: ");
  677.             io.put_string(hexa4_at(index + 1));
  678.             Result := index + 5;
  679.          when Constant_long then -- CONSTANT_Long :
  680.             io.put_string("long: ");
  681.             io.put_string(hexa8_at(index + 1));
  682.             Result := index + 9;
  683.          when Constant_double then -- CONSTANT_Double :
  684.             io.put_string("double: ");
  685.             io.put_string(hexa8_at(index + 1));
  686.             Result := index + 9;
  687.          when Constant_name_and_type then -- CONSTANT_NameandType :
  688.             io.put_string("name: ");
  689.             name_idx := u2_to_integer(info.substring(1,2));
  690.             if constant_pool.valid_index(name_idx) then
  691.                cp_info := constant_pool.item(name_idx);
  692.                if cp_info.tag.code = 1 then
  693.                   tmp_string.clear;
  694.                   constant_pool.view_in(tmp_string,name_idx);
  695.                   io.put_string(tmp_string);
  696.                   io.put_string(" type: ");
  697.                   type_idx := u2_to_integer(info.substring(3,4));
  698.                   if constant_pool.valid_index(type_idx) then
  699.                      cp_info := constant_pool.item(type_idx);
  700.                      if cp_info.tag.code = 1 then
  701.                         tmp_string.clear;
  702.                         constant_pool.view_in(tmp_string,type_idx);
  703.                         io.put_string(tmp_string);
  704.                      else
  705.                         io.put_string("??%NUtf8 index expected.%N");
  706.                         bad_class_file("Bad constant pool.",index + 3);
  707.                      end;
  708.                   else
  709.                      io.put_string("%NType index out of range.%N");
  710.                      bad_class_file("Bad constant pool.",index + 3);
  711.                   end;
  712.                else
  713.                   io.put_string("%NUtf8 index expected.%N");
  714.                   bad_class_file("Bad constant pool.",index + 1);
  715.                end;
  716.             else
  717.                io.put_string("??%NClass index out of range.%N");
  718.                bad_class_file("Bad constant pool.",index + 1);
  719.             end;
  720.             Result := index + 5;
  721.          when Constant_utf8 then -- CONSTANT_Utf8 :
  722.             io.put_string("utf8: %"");
  723.             tmp_string.clear;
  724.             constant_pool.view_in(tmp_string,i);
  725.             io.put_string(tmp_string);
  726.             io.put_string("%"");
  727.             Result := index + 1 + cp_info.info.count;
  728.          end;
  729.       end;
  730.  
  731.    print_cp_info_fields_methods(index: INTEGER; info: STRING) is
  732.       require
  733.  
  734.       local
  735.          cp_info: CP_INFO;
  736.          class_idx, utf8_idx, name_and_type_idx: INTEGER;
  737.       do
  738.          class_idx := u2_to_integer(info.substring(1,2));
  739.          name_and_type_idx := u2_to_integer(info.substring(3,4));
  740.          if constant_pool.valid_index(class_idx) then
  741.             cp_info := constant_pool.item(class_idx);
  742.             if cp_info.tag.code = 7 then
  743.                utf8_idx := u2_to_integer(cp_info.info);
  744.                if constant_pool.valid_index(utf8_idx) then
  745.                   tmp_string.clear;
  746.                   constant_pool.view_in(tmp_string,class_idx);
  747.                   io.put_string(tmp_string);
  748.                   io.put_string(" name_and_type: ");
  749.                   if constant_pool.valid_index(name_and_type_idx) then
  750.                      tmp_string.clear;
  751.                      constant_pool.view_in(tmp_string,name_and_type_idx);
  752.                      io.put_string(tmp_string);
  753.                   else
  754.                      io.put_string("??%N*** Error: name_and_type_index expected.");
  755.                      bad_class_file("Bad constant pool.",index + 3);
  756.                   end;
  757.                else
  758.                   io.put_string("??%N*** Error: Class index expected.");
  759.                end;
  760.             else
  761.                io.put_string("%NClass index expected.%N");
  762.                bad_class_file("Bad constant pool.",index + 1);
  763.             end;
  764.          else
  765.             io.put_string("??%NClass index out of range.%N");
  766.             bad_class_file("Bad constant pool.",index + 1);
  767.          end;
  768.       end;
  769.  
  770. feature {NONE}
  771.  
  772.    print_field_info(index: INTEGER): INTEGER is
  773.       local
  774.          access_flags_idx, name_idx: INTEGER;
  775.          descriptor_idx, field_attributes_count: INTEGER;
  776.          access_flags: BIT Integer_bits;
  777.       do
  778.          access_flags_idx := index;
  779.          Result := index + 2;
  780.          io.put_string("access flags (");
  781.          io.put_string(hexa2_at(access_flags_idx));
  782.          io.put_string("): ");
  783.          access_flags := bytes.item(access_flags_idx + 1).to_bit;
  784.          if (access_flags and 1B).to_boolean then
  785.             io.put_string("public ");
  786.          end;
  787.          if (access_flags and 10B).to_boolean then
  788.             io.put_string("private ");
  789.          end;
  790.          if (access_flags and 100B).to_boolean then
  791.             io.put_string("protected ");
  792.          end;
  793.          if (access_flags and 1000B).to_boolean then
  794.             io.put_string("static ");
  795.          end;
  796.          if (access_flags and 10000B).to_boolean then
  797.             io.put_string("final ");
  798.          end;
  799.          if (access_flags and 1000000B).to_boolean then
  800.             io.put_string("volatile ");
  801.          end;
  802.          if (access_flags and 10000000B).to_boolean then
  803.             io.put_string("transient ");
  804.          end;
  805.          io.put_new_line;
  806.          io.put_string("Field name: ");
  807.          name_idx := u2_integer_at(Result);
  808.          Result := Result + 2;
  809.          if constant_pool.valid_index(name_idx) then
  810.             tmp_string.clear;
  811.             constant_pool.view_in(tmp_string,name_idx);
  812.             io.put_string(tmp_string);
  813.             descriptor_idx := u2_integer_at(Result);
  814.             Result := Result + 2;
  815.             io.put_string(" descriptor: ");
  816.             if constant_pool.valid_index(descriptor_idx) then
  817.                tmp_string.clear;
  818.                constant_pool.view_in(tmp_string,descriptor_idx);
  819.                io.put_string(tmp_string);
  820.                field_attributes_count := u2_integer_at(Result);
  821.                Result := Result + 2;
  822.                io.put_new_line;
  823.                io.put_string("Attributes count: ");
  824.                io.put_integer(field_attributes_count);
  825.                io.put_new_line;
  826.                from
  827.                until
  828.                   field_attributes_count = 0
  829.                loop
  830.                   Result := print_attribute_info(Result);
  831.                   field_attributes_count := field_attributes_count - 1;
  832.                end;
  833.             else
  834.                io.put_string("??%NDescriptor index out of range.%N");
  835.                bad_class_file("Bad constant pool.",Result - 2);
  836.             end;
  837.          else
  838.             io.put_string("??%NName index out of range.%N");
  839.             bad_class_file("Bad constant pool.",Result - 2);
  840.          end;
  841.       end;
  842.  
  843.    print_attribute_info(index: INTEGER): INTEGER is
  844.       local
  845.          attribute_name_idx, attribute_length: INTEGER;
  846.          attribute_name: STRING;
  847.          tmp: INTEGER;
  848.       do
  849.          attribute_name_idx := u2_integer_at(index);
  850.          Result := index + 2;
  851.          io.put_string("Attribute Name: ");
  852.          tmp_string.clear;
  853.          constant_pool.view_in(tmp_string,attribute_name_idx);
  854.          io.put_string(tmp_string);
  855.          attribute_name := tmp_string.twin;
  856.          attribute_length := u4_integer_at(Result);
  857.          Result := Result + 4;
  858.          io.put_string(" length: ");
  859.          io.put_integer(attribute_length);
  860.          io.put_character(' ');
  861.          if ("Code").is_equal(attribute_name) then
  862.             tmp := print_code_attribute(Result,attribute_length);
  863.             Result := Result + attribute_length;
  864.          else
  865.             io.put_string(" Ignored (skipped)%N");
  866.             Result := Result + attribute_length;
  867.          end;
  868.       end;
  869.  
  870.  
  871.    print_method_info(index: INTEGER): INTEGER is
  872.       local
  873.          access_flags_idx, name_idx: INTEGER;
  874.          descriptor_idx, method_attributes_count: INTEGER;
  875.          access_flags: BIT Integer_bits;
  876.       do
  877.          access_flags_idx := index;
  878.          Result := index + 2;
  879.          io.put_string("access flags (");
  880.          io.put_string(hexa2_at(access_flags_idx));
  881.          io.put_string("): ");
  882.          access_flags := bytes.item(access_flags_idx + 1).to_bit;
  883.          if (access_flags and 1B).to_boolean then
  884.             io.put_string("public ");
  885.          end;
  886.          if (access_flags and 10B).to_boolean then
  887.             io.put_string("private ");
  888.          end;
  889.          if (access_flags and 100B).to_boolean then
  890.             io.put_string("protected ");
  891.          end;
  892.          if (access_flags and 1000B).to_boolean then
  893.             io.put_string("static ");
  894.          end;
  895.          if (access_flags and 10000B).to_boolean then
  896.             io.put_string("final ");
  897.          end;
  898.          if (access_flags and 100000B).to_boolean then
  899.             io.put_string("synchronized ");
  900.          end;
  901.          access_flags := bytes.item(access_flags_idx).to_bit;
  902.          if (access_flags and 1B).to_boolean then
  903.             io.put_string("native ");
  904.          end;
  905.          if (access_flags and 100B).to_boolean then
  906.             io.put_string("abstract ");
  907.          end;
  908.          io.put_new_line;
  909.          name_idx := u2_integer_at(Result);
  910.          Result := Result + 2;
  911.          io.put_string("Method name: ");
  912.          tmp_string.clear;
  913.          constant_pool.view_in(tmp_string,name_idx);
  914.          io.put_string(tmp_string);
  915.          io.put_string(" descriptor: ");
  916.          descriptor_idx := u2_integer_at(Result);
  917.          Result := Result + 2;
  918.          tmp_string.clear;
  919.          constant_pool.view_in(tmp_string,descriptor_idx);
  920.          io.put_string(tmp_string);
  921.          io.put_new_line;
  922.          io.put_string("Attributes count: ");
  923.          method_attributes_count := u2_integer_at(Result);
  924.          Result := Result + 2;
  925.          io.put_integer(method_attributes_count);
  926.          io.put_new_line;
  927.          from
  928.          until
  929.             method_attributes_count = 0
  930.          loop
  931.             Result := print_attribute_info(Result);
  932.             method_attributes_count := method_attributes_count - 1;
  933.          end;
  934.       end;
  935.  
  936.    print_code_attribute(index, length: INTEGER): INTEGER is
  937.       local
  938.          code_length: INTEGER;
  939.          exception_table_length: INTEGER;
  940.          max_stack, max_locals: INTEGER;
  941.          -- idx: INTEGER;
  942.          local_attributes_count: INTEGER;
  943.       do
  944.          io.put_string("%Nmax_stack: ");
  945.          max_stack := u2_integer_at(index);
  946.          Result := index + 2;
  947.          io.put_integer(max_stack);
  948.          io.put_string(" max_locals: ");
  949.          max_locals := u2_integer_at(Result);
  950.          Result := Result + 2;
  951.          io.put_integer(max_locals);
  952.          io.put_string(" code_length: ");
  953.          code_length := u4_integer_at(Result);
  954.          Result := Result + 4;
  955.          io.put_integer(code_length);
  956.          io.put_new_line;
  957.          print_byte_code(Result,code_length);
  958.          Result := Result + code_length;
  959.          exception_table_length := u2_integer_at(Result);
  960.          Result := Result + 2;
  961.          io.put_string("Exception(s): ");
  962.          io.put_integer(exception_table_length);
  963.          io.put_new_line;
  964.          print_exception_table(Result,exception_table_length);
  965.          Result := Result + exception_table_length * 8;
  966.          io.put_string("Attributes count: ");
  967.          local_attributes_count := u2_integer_at(Result);
  968.          Result := Result + 2;
  969.          io.put_integer(local_attributes_count);
  970.          io.put_new_line;
  971.          from
  972.          until
  973.             local_attributes_count = 0
  974.          loop
  975.             Result := print_attribute_info(Result);
  976.             local_attributes_count := local_attributes_count - 1;
  977.          end;
  978.       end;
  979.  
  980.    inst_view(byte_idx: INTEGER; cp_idx_type: CHARACTER) is
  981.       local
  982.          cp_idx: INTEGER;
  983.          cp_info: CP_INFO;
  984.       do
  985.          cp_idx := u2_integer_at(byte_idx);
  986.          if constant_pool.valid_index(cp_idx) then
  987.             cp_info := constant_pool.item(cp_idx);
  988.             if cp_info.tag = cp_idx_type then
  989.                constant_pool.view_in(inst,cp_idx);
  990.             else
  991.                tmp_string.clear;
  992.                tmp_string.append("????%N");
  993.                tmp_string.append("Invalid type entry in constant pool at: ");
  994.                cp_idx.append_in(tmp_string);
  995.                tmp_string.append(" : ");
  996.                constant_pool.view_in(tmp_string,cp_idx);
  997.                tmp_string.append("%NExpected tag: ");
  998.                cp_idx_type.code.append_in(tmp_string);
  999.                tmp_string.append(" (");
  1000.                cp_info_tag_name_in(cp_idx_type,tmp_string);
  1001.                tmp_string.append(")%NActual   tag: ");
  1002.                cp_info.tag.code.append_in(tmp_string);
  1003.                tmp_string.append(" (");
  1004.                cp_info_tag_name_in(cp_info.tag,tmp_string);
  1005.                tmp_string.append(")%N");
  1006.                io.put_string(tmp_string);
  1007.                bad_class_file("Constant pool type index error.",byte_idx);
  1008.             end;
  1009.          else
  1010.             io.put_string("????%N");
  1011.             bad_class_file("Valid index in constant pool expected.",byte_idx);
  1012.          end;
  1013.       end;
  1014.  
  1015.    u2sign_extended_view(str: STRING; idx: INTEGER) is
  1016.       local
  1017.          byte: INTEGER;
  1018.       do
  1019.          byte := bytes.item(idx);
  1020.          str.append(hexa1_at(idx));
  1021.          str.append(" (");
  1022.          if byte < 128 then
  1023.             byte.append_in(str);
  1024.          else
  1025.             (byte - 256).append_in(str)
  1026.          end;
  1027.          str.append(")");
  1028.       end;
  1029.  
  1030.    print_one_instruction(pc_idx, pc: INTEGER): INTEGER is
  1031.          -- Return the following `pc_idx'.
  1032.       local
  1033.          opcode: INTEGER;
  1034.          idx: INTEGER;
  1035.       do
  1036.          Result := pc_idx + 1;
  1037.          opcode := bytes.item(pc_idx);
  1038.          inspect
  1039.             opcode
  1040.          when 0 then
  1041.             inst_opcode("nop (Do nothing)");
  1042.          when 1 then
  1043.             inst_opcode("aconst_null (Push null)");
  1044.          when 2 then
  1045.             inst_opcode("iconst_m1 (Push int -1)");
  1046.          when 3 .. 8 then
  1047.             inst_opcode("iconst_");
  1048.             (opcode - 3).append_in(inst);
  1049.             inst.append(" (Push int ");
  1050.             (opcode - 3).append_in(inst);
  1051.             inst.extend(')');
  1052.          when 9 then
  1053.             inst_opcode("lconst_0 (Push long 0)");
  1054.          when 10 then
  1055.             inst_opcode("lconst_1 (Push long 1)");
  1056.          when 11 .. 13 then
  1057.             inst_opcode("fconst_");
  1058.             (opcode - 11).append_in(inst);
  1059.          when 14 .. 15 then
  1060.             inst_opcode("dconst_");
  1061.             (opcode - 14).append_in(inst);
  1062.          when 16 then
  1063.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1064.             inst_opcode("bipush ");
  1065.             u2sign_extended_view(inst,pc_idx + 1);
  1066.             Result := Result + 1;
  1067.          when 17 then
  1068.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1069.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1070.             inst_opcode("sipush ");
  1071.             inst.append(hexa2_at(pc_idx + 1));
  1072.             inst_opcode("(Push short with sign-extension)");
  1073.             Result := Result + 2;
  1074.          when 18 then
  1075.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1076.             idx := bytes.item(pc_idx + 1);
  1077.             inst_opcode("ldc at ");
  1078.             idx.append_in(inst);
  1079.             inst.append(" : ");
  1080.             if constant_pool.valid_index(idx) then
  1081.                constant_pool.view_in(inst,idx);
  1082.             else
  1083.                io.put_string("??%N");
  1084.                bad_class_file("Constant pool index out of range.",pc_idx + 1);
  1085.             end;
  1086.             Result := Result + 1;
  1087.          when 19 then
  1088.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1089.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1090.             inst_opcode("ldc_w ");
  1091.             idx := u2_integer_at(pc_idx + 1);
  1092.             if constant_pool.valid_index(idx) then
  1093.                constant_pool.view_in(inst,idx);
  1094.             else
  1095.                io.put_string("????%N");
  1096.                bad_class_file("Constant pool index out of range.",pc_idx + 1);
  1097.             end;
  1098.             Result := Result + 2;
  1099.          when 20 then
  1100.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1101.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1102.             inst_opcode("ldc2_w ");
  1103.             idx := u2_integer_at(pc_idx + 1);
  1104.             if constant_pool.valid_index(idx) then
  1105.                constant_pool.view_in(inst,idx);
  1106.             else
  1107.                io.put_string("????%N");
  1108.                bad_class_file("CONSTANT_Long or CONSTANT_Double expected.",pc_idx + 1);
  1109.             end;
  1110.             Result := Result + 2;
  1111.          when 21 then
  1112.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1113.             inst_opcode("iload ");
  1114.             bytes.item(pc_idx + 1).append_in(inst);
  1115.             inst.append(" (load int from local #");
  1116.             bytes.item(pc_idx + 1).append_in(inst);
  1117.             inst.extend(')');
  1118.             Result := Result + 1;
  1119.          when 22 then
  1120.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1121.             inst_opcode("lload ");
  1122.             bytes.item(pc_idx + 1).append_in(inst);
  1123.             inst.append(" (load long from local #");
  1124.             bytes.item(pc_idx + 1).append_in(inst);
  1125.             inst.extend(')');
  1126.             Result := Result + 1;
  1127.          when 23 then
  1128.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1129.             inst_opcode("fload ");
  1130.             bytes.item(pc_idx + 1).append_in(inst);
  1131.             inst.append(" (load float from local #");
  1132.             bytes.item(pc_idx + 1).append_in(inst);
  1133.             inst.extend(')');
  1134.             Result := Result + 1;
  1135.          when 24 then
  1136.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1137.             inst_opcode("dload ");
  1138.             bytes.item(pc_idx + 1).append_in(inst);
  1139.             inst.append(" (load double from local #");
  1140.             bytes.item(pc_idx + 1).append_in(inst);
  1141.             inst.extend(')');
  1142.             Result := Result + 1;
  1143.          when 25 then
  1144.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1145.             inst_opcode("aload ");
  1146.             bytes.item(pc_idx + 1).append_in(inst);
  1147.             inst.append(" (load reference from local #");
  1148.             bytes.item(pc_idx + 1).append_in(inst);
  1149.             inst.extend(')');
  1150.             Result := Result + 1;
  1151.          when 26 .. 29 then
  1152.             inst_opcode("iload_");
  1153.             (opcode - 26).append_in(inst);
  1154.             inst.append(" (load int from local #");
  1155.             (opcode - 26).append_in(inst);
  1156.             inst.extend(')');
  1157.          when 30 .. 33 then
  1158.             inst_opcode("lload_");
  1159.             (opcode - 30).append_in(inst);
  1160.             inst.append(" (load long from local #");
  1161.             (opcode - 30).append_in(inst);
  1162.             inst.extend(')');
  1163.          when 34 .. 37 then
  1164.             inst_opcode("fload_");
  1165.             (opcode - 34).append_in(inst);
  1166.             inst.append(" (load float from local #");
  1167.             (opcode - 34).append_in(inst);
  1168.             inst.extend(')');
  1169.          when 38 .. 41 then
  1170.             inst_opcode("dload_");
  1171.             (opcode - 38).append_in(inst);
  1172.             inst.append(" (load double from local #");
  1173.             (opcode - 38).append_in(inst);
  1174.             inst.extend(')');
  1175.          when 42 .. 45 then
  1176.             inst_opcode("aload_");
  1177.             (opcode - 42).append_in(inst);
  1178.             inst.append(" (load reference from local #");
  1179.             (opcode - 42).append_in(inst);
  1180.             inst.extend(')');
  1181.          when 46 then
  1182.             inst_opcode("iaload");
  1183.          when 47 then
  1184.             inst_opcode("laload");
  1185.          when 48 then
  1186.             inst_opcode("faload");
  1187.          when 49 then
  1188.             inst_opcode("daload");
  1189.          when 50 then
  1190.             inst_opcode("aaload");
  1191.          when 51 then
  1192.             inst_opcode("baload");
  1193.          when 52 then
  1194.             inst_opcode("caload");
  1195.          when 53 then
  1196.             inst_opcode("saload");
  1197.          when 54 then
  1198.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1199.             inst_opcode("istore ");
  1200.             bytes.item(pc_idx + 1).append_in(inst);
  1201.             inst.append(" (store int into local #");
  1202.             bytes.item(pc_idx + 1).append_in(inst);
  1203.             inst.extend(')');
  1204.             Result := Result + 1;
  1205.          when 55 then
  1206.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1207.             inst_opcode("lstore ");
  1208.             bytes.item(pc_idx + 1).append_in(inst);
  1209.             inst.append(" (store long into local #");
  1210.             bytes.item(pc_idx + 1).append_in(inst);
  1211.             inst.extend(')');
  1212.             Result := Result + 1;
  1213.          when 56 then
  1214.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1215.             inst_opcode("fstore ");
  1216.             bytes.item(pc_idx + 1).append_in(inst);
  1217.             inst.append(" (store float into local #");
  1218.             bytes.item(pc_idx + 1).append_in(inst);
  1219.             inst.extend(')');
  1220.             Result := Result + 1;
  1221.          when 57 then
  1222.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1223.             inst_opcode("dstore ");
  1224.             bytes.item(pc_idx + 1).append_in(inst);
  1225.             inst.append(" (store double into local #");
  1226.             bytes.item(pc_idx + 1).append_in(inst);
  1227.             inst.extend(')');
  1228.             Result := Result + 1;
  1229.          when 58 then
  1230.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1231.             inst_opcode("astore ");
  1232.             bytes.item(pc_idx + 1).append_in(inst);
  1233.             inst.append(" (store reference into local #");
  1234.             bytes.item(pc_idx + 1).append_in(inst);
  1235.             inst.extend(')');
  1236.             Result := Result + 1;
  1237.          when 59 .. 62 then
  1238.             inst_opcode("istore_");
  1239.             (opcode - 59).append_in(inst);
  1240.          when 63 .. 66 then
  1241.             inst_opcode("lstore_");
  1242.             (opcode - 63).append_in(inst);
  1243.             inst.append(" (store long into local #");
  1244.             (opcode - 63).append_in(inst);
  1245.             inst.extend(')');
  1246.          when 67 .. 70 then
  1247.             inst_opcode("fstore_");
  1248.             (opcode - 67).append_in(inst);
  1249.             inst.append(" (store float into local #");
  1250.             (opcode - 67).append_in(inst);
  1251.             inst.extend(')');
  1252.          when 71 .. 74 then
  1253.             inst_opcode("dstore_");
  1254.             (opcode - 71).append_in(inst);
  1255.             inst.append(" (store double into local #");
  1256.             (opcode - 71).append_in(inst);
  1257.             inst.extend(')');
  1258.          when 75 .. 78 then
  1259.             inst_opcode("astore_");
  1260.             (opcode - 75).append_in(inst);
  1261.             inst.append(" (store reference into local #");
  1262.             (opcode - 75).append_in(inst);
  1263.             inst.extend(')');
  1264.          when 79 then
  1265.             inst_opcode("iastore");
  1266.          when 80 then
  1267.             inst_opcode("lastore");
  1268.          when 81 then
  1269.             inst_opcode("fastore");
  1270.          when 82 then
  1271.             inst_opcode("dastore");
  1272.          when 83 then
  1273.             inst_opcode("aastore");
  1274.          when 84 then
  1275.             inst_opcode("bastore");
  1276.          when 85 then
  1277.             inst_opcode("castore");
  1278.          when 86 then
  1279.             inst_opcode("sastore");
  1280.          when 87 then
  1281.             inst_opcode("pop (...,w => ...)");
  1282.          when 88 then
  1283.             inst_opcode("pop2 (...,w1,w2 => ...)");
  1284.          when 89 then
  1285.             inst_opcode("dup (...,w => ...,w,w)");
  1286.          when 90 then
  1287.             inst_opcode("dup_x1 (...,w2,w1 => ...,w1,w2,w1)");
  1288.          when 91 then
  1289.             inst_opcode("dup_x2 (...,w3,w2,w1 => ...,w1,w3,w2,w1)");
  1290.          when 92 then
  1291.             inst_opcode("dup2 (...,w2,w1 => ...,w2,w1,w2,w1)");
  1292.          when 93 then
  1293.             inst_opcode("dup2_x1 (...,w3,w2,w1 => ...,w2,w1,w3,w2,w1)");
  1294.          when 94 then
  1295.             inst_opcode("dup2_x2 (...,w4,w3,w2,w1 => ...,w2,w1,w4,w3,w2,w1)");
  1296.          when 95 then
  1297.             inst_opcode("swap (...,w2,w1 => ...,w1,w2)");
  1298.          when 96 then
  1299.             inst_opcode("iadd");
  1300.          when 97 then
  1301.             inst_opcode("ladd");
  1302.          when 98 then
  1303.             inst_opcode("fadd");
  1304.          when 99 then
  1305.             inst_opcode("dadd");
  1306.          when 100 then
  1307.             inst_opcode("isub");
  1308.          when 101 then
  1309.             inst_opcode("lsub");
  1310.          when 102 then
  1311.             inst_opcode("fsub");
  1312.          when 103 then
  1313.             inst_opcode("dsub");
  1314.          when 104 then
  1315.             inst_opcode("imul");
  1316.          when 105 then
  1317.             inst_opcode("lmul");
  1318.          when 106 then
  1319.             inst_opcode("fmul");
  1320.          when 107 then
  1321.             inst_opcode("dmul");
  1322.          when 108 then
  1323.             inst_opcode("idiv");
  1324.          when 109 then
  1325.             inst_opcode("ldiv");
  1326.          when 110 then
  1327.             inst_opcode("fdiv");
  1328.          when 111 then
  1329.             inst_opcode("ddiv");
  1330.          when 112 then
  1331.             inst_opcode("irem");
  1332.          when 116 then
  1333.             inst_opcode("ineg");
  1334.          when 117 then
  1335.             inst_opcode("lneg");
  1336.          when 118 then
  1337.             inst_opcode("fneg");
  1338.          when 119 then
  1339.             inst_opcode("dneg");
  1340.          when 120 then
  1341.             inst_opcode("ishl");
  1342.          when 124 then
  1343.             inst_opcode("iushr");
  1344.          when 126 then
  1345.             inst_opcode("iand");
  1346.          when 128 then
  1347.             inst_opcode("ior");
  1348.          when 130 then
  1349.             inst_opcode("ixor");
  1350.          when 132 then
  1351.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1352.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1353.             inst_opcode("iinc local #");
  1354.             bytes.item(pc_idx + 1).append_in(inst);
  1355.             inst.append(" with: :");
  1356.             inst.append(hexa1_at(pc_idx + 2));
  1357.             inst.append(" (sign-extended)");
  1358.             Result := Result + 2;
  1359.          when 133 then
  1360.             inst_opcode("i2l (Convert int to long)");
  1361.          when 134 then
  1362.             inst_opcode("i2f (Convert int to float)");
  1363.          when 135 then
  1364.             inst_opcode("i2d (Convert int to double)");
  1365.          when 136 then
  1366.             inst_opcode("l2i (Convert long to int)");
  1367.          when 137 then
  1368.             inst_opcode("l2f (Convert long to float)");
  1369.          when 138 then
  1370.             inst_opcode("l2d (Convert long to double)");
  1371.          when 139 then
  1372.             inst_opcode("f2i (Convert float to int)");
  1373.          when 140 then
  1374.             inst_opcode("f2l (Convert float to long)");
  1375.          when 141 then
  1376.             inst_opcode("f2d (Convert float to double)");
  1377.          when 142 then
  1378.             inst_opcode("d2i (Convert double to int)");
  1379.          when 143 then
  1380.             inst_opcode("d2l (Convert double to long)");
  1381.          when 144 then
  1382.             inst_opcode("d2f (Convert double to float)");
  1383.          when 145 then
  1384.             inst_opcode("i2b (Convert int to byte)");
  1385.          when 146 then
  1386.             inst_opcode("i2c (Convert int to char)");
  1387.          when 149 then
  1388.             inst_opcode("fcmpl");
  1389.          when 150 then
  1390.             inst_opcode("fcmpg");
  1391.          when 151 .. 152 then
  1392.             inst_opcode("dcmp");
  1393.             inspect
  1394.                opcode
  1395.             when 151 then
  1396.                inst.append("l");
  1397.             when 152 then
  1398.                inst.append("g");
  1399.             end;
  1400.          when 153 .. 158 then
  1401.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1402.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1403.             inst_opcode("if");
  1404.             inspect
  1405.                opcode
  1406.             when 153 then
  1407.                inst.append("eq");
  1408.             when 154 then
  1409.                inst.append("ne");
  1410.             when 155 then
  1411.                inst.append("lt");
  1412.             when 156 then
  1413.                inst.append("ge");
  1414.             when 157 then
  1415.                inst.append("gt");
  1416.             when 158 then
  1417.                inst.append("le");
  1418.             end;
  1419.             inst.extend(' ');
  1420.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1421.             Result := Result + 2;
  1422.          when 159 .. 166 then
  1423.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1424.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1425.             inst_opcode("if_");
  1426.             inspect
  1427.                opcode
  1428.             when 159 .. 164 then
  1429.                inst.extend('i');
  1430.             else
  1431.                inst.extend('a');
  1432.             end;
  1433.             inst.append("cmp");
  1434.             inspect
  1435.                opcode
  1436.             when 159 then
  1437.                inst.append("eq");
  1438.             when 160 then
  1439.                inst.append("ne");
  1440.             when 161 then
  1441.                inst.append("lt");
  1442.             when 162 then
  1443.                inst.append("ge");
  1444.             when 163 then
  1445.                inst.append("gt");
  1446.             when 164 then
  1447.                inst.append("le");
  1448.             when 165 then
  1449.                inst.append("eq");
  1450.             when 166 then
  1451.                inst.append("ne");
  1452.             end;
  1453.             inst.extend(' ');
  1454.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1455.             Result := Result + 2;
  1456.          when 167 then
  1457.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1458.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1459.             inst_opcode("goto ");
  1460.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1461.             Result := Result + 2;
  1462.          when 172 then
  1463.             inst_opcode("ireturn");
  1464.          when 173 then
  1465.             inst_opcode("lreturn");
  1466.          when 174 then
  1467.             inst_opcode("freturn");
  1468.          when 175 then
  1469.             inst_opcode("dreturn");
  1470.          when 176 then
  1471.             inst_opcode("areturn");
  1472.          when 177 then
  1473.             inst_opcode("return");
  1474.          when 178 then
  1475.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1476.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1477.             inst_opcode("getstatic ");
  1478.             inst_view(pc_idx + 1,Constant_fieldref);
  1479.             Result := Result + 2;
  1480.          when 179 then
  1481.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1482.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1483.             inst_opcode("putstatic ");
  1484.             inst_view(pc_idx + 1,Constant_fieldref);
  1485.             Result := Result + 2;
  1486.          when 180 then
  1487.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1488.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1489.             inst_opcode("getfield ");
  1490.             inst_view(pc_idx + 1,Constant_fieldref);
  1491.             Result := Result + 2;
  1492.          when 181 then
  1493.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1494.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1495.             inst_opcode("putfield ");
  1496.             inst_view(pc_idx + 1,Constant_fieldref);
  1497.             Result := Result + 2;
  1498.          when 182 then
  1499.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1500.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1501.             inst_opcode("invokevirtual ");
  1502.             inst_view(pc_idx + 1,Constant_methodref);
  1503.             Result := Result + 2;
  1504.          when 183 then
  1505.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1506.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1507.             inst_opcode("invokespecial ");
  1508.             inst_view(pc_idx + 1,Constant_methodref);
  1509.             Result := Result + 2;
  1510.          when 184 then
  1511.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1512.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1513.             inst_opcode("invokestatic ");
  1514.             inst_view(pc_idx + 1,Constant_methodref);
  1515.             Result := Result + 2;
  1516.          when 185 then
  1517.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1518.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1519.             inst_opcode("invokeinterface ");
  1520.             inst_view(pc_idx + 1,Constant_interfacemethodref);
  1521.             Result := Result + 2;
  1522.          when 187 then
  1523.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1524.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1525.             inst_opcode("new ");
  1526.             inst_view(pc_idx + 1,Constant_class);
  1527.             Result := Result + 2;
  1528.          when 188 then
  1529.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1530.             inst_opcode("newarray of ");
  1531.             inspect
  1532.                bytes.item(pc_idx + 1)
  1533.             when 4 then
  1534.                inst.append("boolean");
  1535.             when 5 then
  1536.                inst.append("character");
  1537.             when 6 then
  1538.                inst.append("float");
  1539.             when 7 then
  1540.                inst.append("double");
  1541.             when 8 then
  1542.                inst.append("byte");
  1543.             when 9 then
  1544.                inst.append("short");
  1545.             when 10 then
  1546.                inst.append("int");
  1547.             when 11 then
  1548.                inst.append("long");
  1549.             else
  1550.                io.put_string("??%NInvalid newarray instruction.%N");
  1551.                bad_class_file("Bad array type.",pc_idx + 1);
  1552.             end;
  1553.             Result := Result + 1
  1554.          when 189 then
  1555.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1556.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1557.             inst_opcode("anewarray of ");
  1558.             inst_view(pc_idx + 1,Constant_class);
  1559.             Result := Result + 2;
  1560.          when 190 then
  1561.             inst_opcode("arraylength");
  1562.          when 191 then
  1563.             inst_opcode("athrow");
  1564.          when 192 then
  1565.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1566.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1567.             inst_opcode("checkcast ");
  1568.             inst_view(pc_idx + 1,Constant_class);
  1569.             Result := Result + 2;
  1570.          when 193 then
  1571.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1572.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1573.             inst_opcode("instanceof ");
  1574.             inst_view(pc_idx + 1,Constant_class);
  1575.             Result := Result + 2;
  1576.          when 198 then
  1577.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1578.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1579.             inst_opcode("ifnull ");
  1580.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1581.             Result := Result + 2;
  1582.          when 199 then
  1583.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1584.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1585.             inst_opcode("ifnonnull ");
  1586.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1587.             Result := Result + 2;
  1588.          else
  1589.             io.put_string(inst);
  1590.             io.put_new_line;
  1591.             io.put_string("Unknown Opcode: ");
  1592.             io.put_integer(opcode);
  1593.             io.put_string(" (0x");
  1594.             io.put_string(opcode.to_character.to_hexadecimal);
  1595.             io.put_string(")%N");
  1596.             bad_class_file("Unknown Opcode.",pc_idx);
  1597.          end;
  1598.       ensure
  1599.          Result >= pc_idx + 1
  1600.       end;
  1601.  
  1602.    print_byte_code(start_idx, length: INTEGER) is
  1603.          -- Print the byte code stored in range :
  1604.          --    [`start_idx' .. `start_idx' + `length']
  1605.       require
  1606.          bytes.valid_index(start_idx);
  1607.          length >= 0
  1608.       local
  1609.          pc_idx, pc: INTEGER;
  1610.       do
  1611.          from
  1612.             pc_idx := start_idx;
  1613.          until
  1614.             pc_idx = start_idx + length
  1615.          loop
  1616.             pc := pc_idx - start_idx;
  1617.             tmp_string.copy("  ");
  1618.             integer_to_hexa_in(pc,tmp_string);
  1619.             tmp_string.append("  ");
  1620.             pc.append_in(tmp_string);
  1621.             tmp_string.extend(' ');
  1622.             extend_string(tmp_string,' ',12);
  1623.             character_at(pc_idx).to_hexadecimal_in(tmp_string);
  1624.             io.put_string(tmp_string);
  1625.             inst.clear;
  1626.             pc_idx := print_one_instruction(pc_idx, pc_idx - start_idx);
  1627.             io.put_string(inst);
  1628.             io.put_new_line;
  1629.          end;
  1630.       end;
  1631.  
  1632.    print_exception_table(index, length: INTEGER) is
  1633.       local
  1634.          i, idx: INTEGER;
  1635.  
  1636.       do
  1637.          from
  1638.             i := length
  1639.           idx := index;
  1640.          until
  1641.             i = 0
  1642.          loop
  1643.             io.put_string("start:   ");
  1644.           io.put_integer(u2_integer_at(idx));
  1645.             io.put_string("%Nend:     ");
  1646.           io.put_integer(u2_integer_at(idx + 2));
  1647.             io.put_string("%Nhandler: ");
  1648.           io.put_integer(u2_integer_at(idx + 4));
  1649.             io.put_string("%Ntype:    ");
  1650.           io.put_integer(u2_integer_at(idx + 6));
  1651.           inst.copy("");
  1652.             inst_view(idx + 6, Constant_class);
  1653.           io.put_string(" (class ");
  1654.           io.put_string(inst);
  1655.           io.put_string(")%N");
  1656.             i := i - 1;
  1657.           idx := idx + 8;
  1658.          end;
  1659.       end;
  1660.  
  1661. feature {NONE}
  1662.  
  1663.    tmp_string: STRING is
  1664.       once
  1665.          !!Result.make(32);
  1666.       end;
  1667.  
  1668. feature {NONE}
  1669.  
  1670.    inst_opcode(msg: STRING) is
  1671.       do
  1672.          extend_string(inst,' ',4);
  1673.          inst.extend(' ');
  1674.          inst.append(msg);
  1675.       end;
  1676.  
  1677.    inst: STRING is
  1678.       once
  1679.          !!Result.make(80);
  1680.       end;
  1681.  
  1682. feature {NONE}
  1683.  
  1684.    view_pc(offset, pc: INTEGER) is
  1685.       local
  1686.          view: INTEGER;
  1687.          bits: BIT Integer_bits;
  1688.       do
  1689.          if offset < ((2 ^ 15) - 1) then
  1690.             view := pc + offset;
  1691.          else
  1692.             view := (offset - (2 ^ 16)) + pc;
  1693.          end;
  1694.          view.append_in(inst);
  1695.       end;
  1696.  
  1697. end -- PRINT_JVM_CLASS
  1698.  
  1699.